﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace ForumLibrary
{
    public class ForumUser
    {
        private string _username;
        private IObserver _controller;
        private bool _loginState;
        private List<Notification> _notifications;
        private ReaderWriterLock _notificationsLock;
        private const int NOTIFICATION_SIZE = 300;
        private int _notificationsIndexAt;

        public ForumUser(string username, IObserver controller, bool loginState)
        {
            _username = username;
            _controller = controller;
            _loginState = loginState;
            _notifications = new List<Notification>(NOTIFICATION_SIZE);
            _notificationsIndexAt = 0;
            _notificationsLock = new ReaderWriterLock();
        }

        public string Username { get { return _username; } }
        public IObserver Controller { get { return _controller; } set { _controller = value; } }
        public bool LoginState { get { return _loginState; } set { _loginState = value; } }
        public List<Notification> Notifications 
        { 
            get 
            {
                _notificationsLock.AcquireReaderLock(-1);
                List<Notification> notifications = this.DeepClone(_notifications);//deep copy
                foreach (Notification note in _notifications)
                    note.delivered = true;
                _notificationsLock.ReleaseReaderLock();
                return notifications; 
            }
        }

        private List<Notification> DeepClone(List<Notification> sourceLst)
        {
            MemoryStream m = new MemoryStream();
            BinaryFormatter b = new BinaryFormatter();
            b.Serialize(m, sourceLst);
            m.Position = 0;
            return (List<Notification>)b.Deserialize(m);
        }

        public void addNotification(Message messageType, string message)
        {
            _notificationsLock.AcquireWriterLock(-1);
            Notification notification = new Notification(messageType, message);
            int index = _notificationsIndexAt % NOTIFICATION_SIZE;
            if (index >= 0 && index < _notifications.Capacity)
            {
                _notifications.Insert(index, notification);
                _notificationsIndexAt++;
            }
            _notificationsLock.ReleaseWriterLock();
        }

        internal int lastNotificationsNum()
        {
            int lastNoteNum = 0;
            foreach (Notification note in _notifications)
                if(!note.delivered)
                    lastNoteNum++;
            return lastNoteNum;
        }
    }
}
